#include "stm32f10x.h"                  // Device header

static uint16_t CountSensor_Count = 0;

void CountSensor_Init(void)
{
	// 第一步：配置RCC，将涉及到的外设的时钟都打开，不打开时钟外设是无法工作的。
	//         其中 EXTI 和 NVIC 的时钟一直是开着的不用处理。
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   // 开启 APB2 下的 GPIOB 的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);    // 开启 APB2 下的 AFIO  的时钟
	
	
	// 第二步：配置GPIO，选择我们的端口为输入模式。
	// 外部中断推荐的 GPIO 输入模式为 上拉、下拉、浮空.
	GPIO_InitTypeDef GPIO_Init_Structure;
	GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init_Structure.GPIO_Pin = GPIO_Pin_14;
	GPIO_Init_Structure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_Init_Structure);
	
	// 第三步：配置 AFIO，选择我们用的这一路 GPIO，连接到后面的 EXTI。
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);   // GPIOB 一路的配置拨到 PB14
	
	// 第四步：配置EXTI，选择边沿触发方式，比如上升沿、下降沿 或者 双边沿。  选择触发响应方式，可以选择中断响应 和 事件响应。 
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;    // 中断响应还是事件响应
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;// 指定触发中断的有效边沿
	EXTI_Init(&EXTI_InitStructure);
	
	// 第五步：配置 NVIC，给我们这个中断选择一个合适的优先级。
	// 分组方式整个芯片只能用一组.
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);        // 优先级分组选择
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;   // 指定通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        // 指定通道是使能还是失能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  // 指定抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;      // 指定响应优先级
	NVIC_Init(&NVIC_InitStructure);
	
	// 最后通过 NVIC，外部中断信号就能进入CPU了，这样CPU 才能收到中断信号，才能跳转到中断函数里面执行中断程序。 
}

void EXTI15_10_IRQHandler(void)
{
	// 判断 EXTI_Line14 对应的中断标志位是否置 1
	if(EXTI_GetITStatus(EXTI_Line14) == SET && GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
	{
		CountSensor_Count++;
		
		// 一定要清除中断标志, 否则程序会卡在中断标志中
		EXTI_ClearITPendingBit(EXTI_Line14);
	}
}

uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}